package com.piesat.quake.business.station.service.impl;

import com.piesat.common.exception.EntityNotFoundException;
import com.piesat.common.utils.StringUtils;
import com.piesat.quake.business.station.model.Region;
import com.piesat.quake.business.station.model.StationInfo;
import com.piesat.quake.business.station.service.DataService;
import com.piesat.quake.business.station.service.RegionService;
import com.piesat.quake.business.station.service.StationInfoService;
import com.piesat.quake.common.mongo.service.MongoService;
import com.piesat.quake.common.mqtt.MqttGateway;
import com.piesat.quake.common.mqtt.decoder.common.CommonEncoder;
import com.piesat.quake.common.mqtt.decoder.entity.FdData;
import com.piesat.quake.common.mqtt.decoder.entity.TiData;
import com.piesat.quake.common.mqtt.decoder.entity.WcData;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class DataServiceImpl implements DataService {

    private final MongoService mongoService;

    private final MqttGateway gateway;

    private final StationInfoService stationInfoService;
    private final RegionService regionService;

    @Override
    public List<FdData> findFdDataList(String id, Long startTime, Long endTime, Integer rate) {
        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(id));
        query.addCriteria(Criteria.where("timestamp").gte(startTime).lte(endTime));
        List<FdData> fdDataList = mongoService.find(query, FdData.class);
        List<FdData> resultList = new ArrayList<>();
        for (int i = 0; i < fdDataList.size(); i++) {
            if (i % rate == 0) {
                resultList.add(fdDataList.get(i));
            }
        }
        return resultList;
    }

    @Override
    public void startReal(String id) {
        StationInfo info = publish(id, (short) 1, (byte) 1);
        info.setRealStatus(1);
        stationInfoService.updateById(info);
    }

    @Override
    public void stopReal(String id) {
        StationInfo info = publish(id, (short) 1, (byte) 0);
        info.setRealStatus(0);
        stationInfoService.updateById(info);
    }

    @Override
    public void startFtp(String id) {
        StationInfo info = publish(id, (short) 2, (byte) 1);
        info.setFtpStatus(1);
        stationInfoService.updateById(info);
    }

    @Override
    public void stopFtp(String id) {
        StationInfo info = publish(id, (short) 2, (byte) 0);
        info.setFtpStatus(0);
        stationInfoService.updateById(info);
    }

    @Override
    public void reboot(String id) {
        StationInfo info = publish(id, (short) 3, (byte) 1);
        info.setOnline(false);
        stationInfoService.updateById(info);
    }

    @Override
    public List<WcData> findWcDataList(String id, Long startTime, Long endTime, Integer rate) {
        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(id));
        query.addCriteria(Criteria.where("startTime").gte(startTime).lte(endTime));
        List<WcData> wcDataList = mongoService.find(query, WcData.class);
        List<WcData> resultList = new ArrayList<>();
        for (int i = 0; i < wcDataList.size(); i++) {
            if (i % rate == 0) {
                resultList.add(wcDataList.get(i));
            }
        }
        return resultList;
    }

    /**
     * 发布下行控制命令
     *
     * @param ctrl
     * @param command
     */
    private StationInfo publish(String id, Short ctrl, Byte command) {
        StationInfo info = Optional.ofNullable(stationInfoService.getById(id)).orElseThrow(() -> new EntityNotFoundException(StationInfo.class, "id", id));
        byte[] bytes = CommonEncoder.encoder(17, "cc", (int) 17, id, ctrl, command);
        gateway.sendToMqtt("vibrate/" + id + "/ontime/control", bytes);
        return info;
    }


    @Override
    public List<TiData> findTiDataList(int count, String id) {
        Query query = new Query();
        if (StringUtils.isNotBlank(id)) {
            query.addCriteria(Criteria.where("id").is(id));
        }
        query.with(Sort.by(Sort.Direction.DESC, "timestamp")).limit(count);
        return mongoService.find(query, TiData.class);
    }
}
